package com.atguigu.srb.core.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.pojo.entity.*;
import com.atguigu.srb.core.mapper.LendReturnMapper;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.util.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2022-10-24
 */
@Slf4j
@Service
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {
    @Autowired
    LendService lendService;
    @Autowired
    LendItemService lendItemService;
    @Autowired
    LendItemReturnService lendItemReturnService;
    @Autowired
    UserInfoService userInfoService;
    @Autowired
    UserAccountService userAccountService;
    @Autowired
    TransFlowService transFlowService;
    @Override
    public String commitReturn(String id, String token) {
        UserInfo userInfo = userInfoService.checkAccount(token);
        //获取本次还款对象
        LendReturn lendReturn = this.getById(id);
        //获取标的对象
        Long lendId = lendReturn.getLendId();
        Lend lend = lendService.getById(lendId);
        //生成访问hfb接口的自动条件的表单字符串(hfb还款接口地址+参数)
        Map<String, Object> params = new HashMap<>();
        params.put("agentId",HfbConst.AGENT_ID);
        params.put("agentGoodsName",lend.getTitle());
        //使用lendReturn的唯一的编号
        params.put("agentBatchNo", lendReturn.getReturnNo());
        params.put("fromBindCode",userInfo.getBindCode());
        params.put("totalAmt",lendReturn.getTotal());
        params.put("note","还款："+lendReturn.getCurrentPeriod()+" 期");

        //当前用户本期还款，还款成功
        List<Map<String, Object>> data = getData(lendReturn, lend);
        params.put("data", JSON.toJSONString(data));
        params.put("voteFeeAmt",new BigDecimal("0"));
        params.put("returnUrl",HfbConst.BORROW_RETURN_RETURN_URL);
        params.put("notifyUrl",HfbConst.BORROW_RETURN_NOTIFY_URL);
        params.put("timestamp",System.currentTimeMillis());
        params.put("sign", RequestHelper.getSign(params));
        return FormHelper.buildForm(HfbConst.BORROW_RETURN_URL,params);
    }
    //还款后的回调接口
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String commitReturnNotifyUrl(HttpServletRequest request) {
        Map<String, String[]> parameterMap = request.getParameterMap();
        Map<String, Object> map = RequestHelper.switchMap(parameterMap);
        if(!RequestHelper.isSignEquals(map)){
            log.error("还款回调，签名验证失败：{}", JSON.toJSONString(map));
            return "fail";
        }
        if(!"0001".equals(map.get("resultCode"))){
            log.error("还款回调，业务处理失败：{}", JSON.toJSONString(map));
            return "fail";
        }
        //{"totalAmt":"70.04","successNum":"1","resultCode":"0001",
        // "agentBatchNo":"RETURN20221112140512179",
        // "voteFeeAmt":"0","resultMsg":"还款成功","timestamp":"1668233129779"}
        log.info("还款回调，成功：{}", JSON.toJSONString(map));
        //处理还款成功的业务：
        //获取还款对象
        String agentBatchNo = map.get("agentBatchNo").toString();//还款lendReturn的 编号
        LendReturn lendReturn = this.getOne(new LambdaQueryWrapper<LendReturn>()
                .eq(LendReturn::getReturnNo, agentBatchNo));
        //1、扣除借款人账户的余额：
        //1.1 查询借款人账户
        UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getUserId, lendReturn.getUserId())
                .eq(UserAccount::getStatus, 1)
                .orderByDesc(UserAccount::getAmount)
                .last("limit 1"));
        BigDecimal totalAmt = new BigDecimal(map.get("totalAmt").toString());
        userAccount.setAmount(userAccount.getAmount().subtract(totalAmt));
        //1.2 更新
        userAccountService.updateById(userAccount);
        UserInfo userInfo = userInfoService.getById(userAccount.getUserId());
        //保存借款人账户还款日志
        TransFlow transFlow = new TransFlow();
        transFlow.setUserName(userInfo.getName());
        transFlow.setUserId(userInfo.getId());
        transFlow.setTransType(7);
        transFlow.setTransTypeName("还款");
        transFlow.setTransNo(agentBatchNo);
        transFlow.setTransAmount(totalAmt);
        transFlow.setMemo(JSON.toJSONString(map));
        transFlowService.save(transFlow);

        //2、 修改还款状态为已还款
        lendReturn.setStatus(1);
        this.updateById(lendReturn);
        //3、投资人账户增加回款金额//4、更新回款对象为已回款
        //获取lendReturn的所有的回款信息集合
        List<LendItemReturn> lendItemReturns = lendItemReturnService
                .list(new LambdaQueryWrapper<LendItemReturn>()
                .eq(LendItemReturn::getLendId, lendReturn.getLendId())
                .eq(LendItemReturn::getCurrentPeriod, lendReturn.getCurrentPeriod()));
        lendItemReturns.forEach(lendItemReturn -> {
            //修改每个回款的状态为已回款
            lendItemReturn.setStatus(1);
            lendItemReturnService.updateById(lendItemReturn);
            //修改lendItemReturn的投资人的账户入账
            UserAccount investUserAccount = userAccountService.getOne(new LambdaQueryWrapper<UserAccount>()
                    .eq(UserAccount::getUserId, lendItemReturn.getInvestUserId())
                    .eq(UserAccount::getStatus, 1)
                    .orderByDesc(UserAccount::getAmount)
                    .last("limit 1"));
            investUserAccount.setAmount(investUserAccount.getAmount().add(lendItemReturn.getTotal()));
            userAccountService.updateById(investUserAccount);
            UserInfo investUserInfo = userInfoService.getById(investUserAccount.getUserId());
            //保存投资人账户入账日志
            TransFlow transFlow2 = new TransFlow();
            transFlow2.setUserName(investUserInfo.getName());
            transFlow2.setUserId(investUserInfo.getId());
            transFlow2.setTransType(4);
            transFlow2.setTransTypeName("投资回款");
            transFlow2.setTransNo(LendNoUtils.getNo());
            transFlow2.setTransAmount(lendItemReturn.getTotal());
            transFlow2.setMemo(JSON.toJSONString(investUserAccount));
            transFlowService.save(transFlow2);

        });

        //5、保存交易日志

        return "success";
    }

    //hfb可以根据指定的投资人投资的本期还款的信息，将用户还款后的钱转给投资人
    public List<Map<String, Object>> getData(LendReturn lendReturn ,Lend lend ) {

        List<Map<String, Object>> returnDetails = new ArrayList<>();
        //根据当前还款记录中的标的id 和自己的期数 查询当前标的所有的 回款记录
        List<LendItemReturn> lendItemReturns = lendItemReturnService.list(new LambdaQueryWrapper<LendItemReturn>()
                .eq(LendItemReturn::getLendId, lend.getId())
                .eq(LendItemReturn::getCurrentPeriod, lendReturn.getCurrentPeriod()));
        lendItemReturns.forEach(lendItemReturn -> {
            /*
            "agent_project_code": "p0001", //标的id
         "vote_bill_no": "tz001", //投资单号(lend_item)
         "to_bind_code":"10516160001061805", //投资人bindCode
         "transit_amt": 11.00, //还款金额
         "base_amt": 10.00,//还款本金
         "benifit_amt": 1.00,//还款利息
         "fee_amt": 0.01 //商户手续费
         */
            LendItem lendItem = lendItemService.getById(lendItemReturn.getLendItemId());
            UserInfo userInfo = userInfoService.getById(lendItem.getInvestUserId());
            Map<String, Object> lendItemReturnMap = new HashMap<>();
            lendItemReturnMap.put("agentProjectCode",lend.getLendNo());
            //本次回款计划 投资的编号  lendItem的编号
            lendItemReturnMap.put("voteBillNo",lendItem.getLendItemNo());
            lendItemReturnMap.put("toBindCode",userInfo.getBindCode());//投资人bindCode
            lendItemReturnMap.put("transitAmt",lendItemReturn.getTotal());//回款金额
            lendItemReturnMap.put("baseAmt",lendItemReturn.getPrincipal());
            lendItemReturnMap.put("benifitAmt",lendItemReturn.getInterest());
            lendItemReturnMap.put("feeAmt",new BigDecimal("0"));
            returnDetails.add(lendItemReturnMap);

        });
        //还款的标的的编号(之前标的放款时，hfb使用标的的编号保存了一条标的记录)
        return returnDetails;
    }
}
